﻿using System;
using System.Collections.Generic;

using System.Text;

namespace RoughJs.Ast
{
    public abstract class XMLLib
    {
        private static Object XML_LIB_KEY = new Object();

        ///**
        //    An object which specifies an XMLLib implementation to be used at runtime.
	 
        //    This interface should be considered experimental.  It may be better
        //    (and certainly more flexible) to write an interface that returns an
        //    XMLLib object rather than a class name, for example.  But that would
        //    cause many more ripple effects in the code, all the way back to
        //    {@link ScriptRuntime}.
        // */
        //public  class Factory
        //{
        //    public static Factory create(String className)
        //    {
        //        return new Factory();

        //    }

        //    public virtual String getImplementationClassName()
        //    {
        //        return className;
        //    }
        //}
        //public class FactoryC : Factory
        //{
        //    public override string getImplementationClassName()
        //    {
        //        return base.getImplementationClassName();
        //    }
        //}

        public static XMLLib extractFromScopeOrNull(Scriptable scope)
        {
            ScriptableObject so = ScriptRuntime.getLibraryScopeOrNull(scope);
            if (so == null)
            {
                // If library is not yet initialized, return null
                return null;
            }

            // Ensure lazily initialization of real XML library instance
            // which is done on first access to XML property
            ScriptableObject.getProperty(so, "XML");

            return (XMLLib)so.getAssociatedValue(XML_LIB_KEY);
        }

        public static XMLLib extractFromScope(Scriptable scope)
        {
            XMLLib lib = extractFromScopeOrNull(scope);
            if (lib != null)
            {
                return lib;
            }
            String msg = ScriptRuntime.getMessage0("msg.XML.not.available");
            throw Context.reportRuntimeError(msg);
        }

        protected XMLLib bindToScope(Scriptable scope)
        {
            ScriptableObject so = ScriptRuntime.getLibraryScopeOrNull(scope);
            if (so == null)
            {
                // standard library should be initialized at this point
                throw new Exception();
            }
            return (XMLLib)so.associateValue(XML_LIB_KEY, this);
        }

        public abstract bool isXMLName(Context cx, Object name);

        public abstract Ref nameRef(Context cx, Object name,
                                    Scriptable scope, int memberTypeFlags);

        public abstract Ref nameRef(Context cx, Object namespace1, Object name,
                                    Scriptable scope, int memberTypeFlags);

        /**
         * Escapes the reserved characters in a value of an attribute.
         *
         * @param value Unescaped text
         * @return The escaped text
         */
        public abstract String escapeAttributeValue(Object value);

        /**
         * Escapes the reserved characters in a value of a text node.
         *
         * @param value Unescaped text
         * @return The escaped text
         */
        public abstract String escapeTextValue(Object value);


        /**
         * Construct namespace for default xml statement.
         */
        public abstract Object toDefaultXmlNamespace(Context cx, Object uriValue);

        public void setIgnoreComments(bool b)
        {
            throw new NotSupportedException();
        }

        public void setIgnoreWhitespace(bool b)
        {
            throw new NotSupportedException();
        }

        public void setIgnoreProcessingInstructions(bool b)
        {
            throw new NotSupportedException();
        }

        public void setPrettyPrinting(bool b)
        {
            throw new NotSupportedException();
        }

        public void setPrettyIndent(int i)
        {
            throw new NotSupportedException();
        }

        public bool isIgnoreComments()
        {
            throw new NotSupportedException();
        }

        public bool isIgnoreProcessingInstructions()
        {
            throw new NotSupportedException();
        }

        public bool isIgnoreWhitespace()
        {
            throw new NotSupportedException();
        }

        public bool isPrettyPrinting()
        {
            throw new NotSupportedException();
        }

        public int getPrettyIndent()
        {
            throw new NotSupportedException();
        }
    }
}
